package utils

import (
	"communication-system/common/messages"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"time"

	"github.com/gomodule/redigo/redis"
)

//该go文件主要是提供该项目的工具函数
//将工具函数关联到结构体中
type TransFer struct {
	Conn net.Conn
	Buf  [4096]byte
}

//从对方读取数据操作，任何地方都可以调用，无论是server还是client
func (transFer *TransFer) Readpkg() (mes messages.Message, err error) {
	//
	fmt.Println("开始尝试读取数据...")
	_, err = transFer.Conn.Read(transFer.Buf[:4])

	if err == io.EOF {
		// fmt.Println("客户端退出连接....,err=")
		return
	}

	fmt.Println("读取的buf:", transFer.Buf[:4])
	//根据buf[:4]转成uint32

	pkglen := binary.BigEndian.Uint32(transFer.Buf[:4])
	//根据pkglen决定一次读取数据的大小

	n, err := transFer.Conn.Read(transFer.Buf[:pkglen])
	if n != int(pkglen) || err != nil {
		return
	}
	//把读取的数据反序列化成message.Message,并返回给使用者
	err = json.Unmarshal(transFer.Buf[:pkglen], &mes)
	if err != nil {
		fmt.Println("服务端接收到的数据反序列化失败...,err=", err)
		return
	}

	return
}

//写数据，发送数据给对方，任何地方都可以调用，无论是server还是client
func (transFer *TransFer) WritePkg(mdata []byte) (err error) {
	//client发送数据mdata给server前需要先发送长度到server,以便server校验数据是否完整
	//获取mdata的长度，然后转换成对应的[]byte大小
	// var pkglen uint32
	pkglen := uint32(len(mdata))
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[:4], pkglen)
	//发送长度
	n, err := transFer.Conn.Write(buf[:4])
	if n != 4 || err != nil {
		fmt.Println("客户端数据发送失败")
		return
	}
	fmt.Printf("本次发送的消息长度%v,消息内容%v\n", len(mdata), string(mdata))
	//发送data
	_, err = transFer.Conn.Write(mdata)
	if err != nil {
		fmt.Println("mdata发送失败...,err=", err)
		return
	}

	return
}

//redis连接池
//定义一个全局的redis pool
var Pool *redis.Pool

func InitPool() {

	Pool = &redis.Pool{
		//连接方法
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", "127.0.0.1:6379")
			if err != nil {
				return nil, err
			}
			c.Do("SELECT", 0)
			return c, nil
		},
		//DialContext:     nil,
		//TestOnBorrow:    nil,
		//最大的空闲连接数，表示即使没有redis连接时依然可以保持N个空闲的连接，而不被清除，随时处于待命状态。
		MaxIdle: 1,
		//最大的激活连接数，表示同时最多有N个连接
		MaxActive: 10,
		//最大的空闲连接等待时间，超过此时间后，空闲连接将被关闭
		IdleTimeout: 180 * time.Second,
		//Wait:            false,
		//MaxConnLifetime: 0,
	}

}
